#!/usr/bin/env python
# coding=utf-8
# Author:  vavava
# Created: 04/11/2012

if __name__ == '__main__':
    """ for file debug"""
    import sys,os
    sys.path.insert(0,os.path.join( os.getcwd(), '..' ))

import re,vavava.util
from ltypes.track_item import TrackItem
from vavava.httpclient import HttpClient
from vavava.base import LogAdapter

__fetch_format__=r'http://auspost.com.au/track/track.html?id=%s'
__ex_folder__=r'page_exception'


class TrackGripper(object):
    """ tracking """
    def __init__(self,dbObj,itemID="",debug_level=0,soc_timeout=10,log=None):
        self.log= LogAdapter(log=log,mod_name=itemID)
        self.item_id=itemID
        self.client = HttpClient(log,debug_level=debug_level,req_timeout=soc_timeout)
        self.client.timeout=11
        self.track_dict={}
        self.fetch_url = __fetch_format__%self.item_id
        self.result_processors={}
        self.exception_processors={}

    def track(self):
        self.log.debug("start tracing(%s):%s"%(self.item_id,self.fetch_url))
        try:
            track_list=self.get_tds()
            self.process_result(*track_list,**self.track_dict)
        except Exception as e:
            self.log.exception(e)

    def get_table(self):
        #self.log.debug("get_table")
        data=self.client.Get(self.fetch_url)
        if data is None:
            text=""
        else:
            text=data.decode('ISO-8859-1','ignore')
        reg_str=r'<a\s*name="emailNotification">[^<]*</a>[^<]*<table[^>]*>.*</table>'
        reg = re.compile(reg_str,re.S)
        match = reg.findall(text)
        if match :
            return match[0]
        else:
            self.process_exception(text,'get_table')

    def get_trs(self):
        #self.log.debug("get_trs")
        table=self.get_table()
        if table:
            reg_str=r'<\s*tr[^>]*>(?P<content>.*?)<\s*/\s*tr\s*>'
            pattern = re.compile(reg_str,re.I+re.DOTALL)
            matches = pattern.findall(table)
            if matches :
                return matches
            else:
                self.process_exception(table,'get_trs')
                return

    def get_tds(self):
        #self.log.debug("get_tds")
        trs=self.get_trs()
        track_list=[]
        if trs:
            for tr in trs:
                itemInfo=TrackItem.parse(self.item_id,tr)
                if itemInfo:
                    track_list.append(itemInfo)
                else:
                    if tr.find("Date/Time") == -1:
                        self.log.warn("WRTrackInfo init failed:"+tr)
        return track_list

    def process_result(self,*track_list,**track_dict):
        # process result
        if len(self.result_processors) < 1:
            # default handler
            self.add_handler(DefaultResultProcessor())
        for each in self.result_processors:
            for processor in self.result_processors[each]:
                processor.process(*track_list,**track_dict)

    def process_exception(self,text,position="",e=None):
        # process result
        if len(self.exception_processors) < 1:
            # default handler
            self.add_handler(DefaultExceptionProcessor())
        for each in self.exception_processors:
            for processor in self.exception_processors[each]:
                processor.process(self.item_id,self.fetch_url,text,position,e)

    def add_handler(self,*handlers):
        for handler in handlers:
            if not hasattr(handler,"handler_order"):
                raise "Invalid handler:%d"%type(handler)
        processors = self.result_processors
        for handler in handlers:
            if handler.handle_type == EXCEPTION_HANDLE:
                processors = self.exception_processors
            if processors.get(handler.handler_order):
                processors[handler.handler_order].append(handler)
            else:
                processors[handler.handler_order]=[handler]

RESULT_HANDLE=1
EXCEPTION_HANDLE=100

class BaseHandler:
    handler_order = RESULT_HANDLE
    handle_type = RESULT_HANDLE

    def add_parent(self, parent):
        self._parent = parent

    def process(self,*param):
        pass

    def __lt__(self, other):
        if not hasattr(other, "handler_order"):
            # Try to preserve the old behavior of having custom classes
            # inserted after default ones (works only for custom user
            # classes which are not aware of handler_order).
            return True
        return self.handler_order < other.handler_order

class DefaultResultProcessor(BaseHandler,LogAdapter):

    def __init__(self,dbObj=None,log=None):
        BaseHandler.handle_type=RESULT_HANDLE
        self.log = LogAdapter(log)
        self.dbObj=dbObj

    def process(self,*track_list,**track_dict):
        if track_list is None or len(track_list)==0:
            self.log.info("Result list is empty")
            return
        for each in track_list:
            if not track_dict.get(each):
                # A new track info
                # each.Name += "debug"
                track_dict[each]=each
                self.log.info("Tracking New tracking info coming:%s,%s,%s,%s"%
                              (each.Name ,each.Description,each.Location,each.TrackTime))
                if self.dbObj:
                    self.dbObj.insert(each)
                # print list
        if track_dict:
            self.log.debug(r"==========Total track info(%s)=========="%len(track_dict))
            for each in track_dict:
                data=track_dict.get(each)
                self.log.debug(r'%s;%s;%s;'%(data.TrackTime,data.Description,data.Location))
            self.log.debug("==========Total track info==========")
        else:
            self.log.debug("==========Total track info==========")
            self.log.debug(r'Result list is empty.')
            self.log.debug("==========Total track info==========")

class DefaultExceptionProcessor(BaseHandler,LogAdapter):

    def __init__(self,log=None):
        BaseHandler.handle_type=EXCEPTION_HANDLE
        self.log = LogAdapter(log)

    def process(self,item_id,fetch_url,text,position="",e=None):
        """ save exception page
        """
        from time import localtime,time
        import codecs,os
        if text is None or text == "":
            return
        t=localtime(time())
        t_str="%d%d%d%d%d%d"%(t.tm_year,t.tm_mon , t.tm_mday,
                              t.tm_hour, t.tm_min, t.tm_sec)
        filename=r'./%s/%s_%s.html'%(__ex_folder__,item_id,t_str)
        vavava.util.assure_path("./%s"%__ex_folder__)
        f=codecs.open(filename,"w",'utf-8')
        file_full_name=os.path.abspath(filename)
        if f:
            f.writelines('<!--' + fetch_url + '--!>'+os.linesep)
            f.write(text)
            f.close()
        self.log.error(r"Failed on get track info(%s): error page saved at %s"%(position,file_full_name))


class TrackGripperWork(TrackGripper,vavava.workqueue.work):
    def __init__(self,dbObj,itemID="",debug_level=0,soc_timeout=10,log=None):
        TrackGripper.__init__(self,dbObj,itemID,debug_level,soc_timeout,log)
        vavava.workqueue.work.__init__(self,log)
        self.add_handler(DefaultExceptionProcessor())
        self.add_handler(DefaultResultProcessor())

    def do(self):
        self.track()

def main():
    import database.dbaccessor
    dbObj = None
    itemID = "UCL0003192"
    dba = database.dbaccessor.DBAccessor()
    dbObj = dba.getConnection()
    gripper = TrackGripper(dbObj,itemID)
    gripper.add_handler(DefaultExceptionProcessor())
    gripper.add_handler(DefaultResultProcessor())
    gripper.add_handler(DefaultResultProcessor())
    gripper.track()

if __name__ == '__main__':
    main()
